/**
  ******************************************************************************
  * @file    w32f006_tsc.c
  * @author  WeiLink Technology
  * @version V1.0.0
  * @date    09/01/2020
  * @brief   This file provides firmware functions to manage the following 
  *          functionalities of Touch Sensor Controller
  *           - Initialization and Configuration
  *           - Data transfers
  *           - Interrupts, events and flags management        
  *  
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, WeiLink Technology SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT WeiLink Technology</center></h2>
  ******************************************************************************  
  */ 

/* Includes ------------------------------------------------------------------*/
#include "w32f006_tsc.h"
#include "w32f006_rcc.h"

/** @addtogroup W32F006_StdPeriph_Driver
  * @{
  */

/** @defgroup TSC 
  * @brief TSC driver modules
  * @{
  */ 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/** @defgroup TSC_Private_Functions
  * @{
  */
/**
  * @brief  Deinitializes the TSC peripheral registers to their default reset values.
  * @retval None
  */
void TSC_DeInit(void)
{
    RCC_APBPeriphResetCmd(RCC_PRESETCTRL_TSC, ENABLE);
    RCC_APBPeriphResetCmd(RCC_PRESETCTRL_TSC, DISABLE);
}

/**
  * @brief  Initializes the TSC peripheral according to the specified parameters
  *         in the TSC_InitStruct.
  * @param  TSC_InitStruct: pointer to a TSC_InitTypeDef structure that contains
  *         the configuration information for TSC.
  * @retval None
  */
void TSC_Init(TSC_InitTypeDef* TSC_InitStruct)
{
    /* Check the TSC parameters */
    assert_param(IS_TSC_DISCARD(TSC_InitStruct->TSC_Discard));
    assert_param(IS_TSC_MODE(TSC_InitStruct->TSC_Mode));
    assert_param(IS_TSC_DIGITAL_PREDIV(TSC_InitStruct->TSC_DigitalPrediv));
    assert_param(IS_TSC_ANALOG_PREDIV(TSC_InitStruct->TSC_AnalogPrediv));
    assert_param(IS_TSC_BIAS_ADJ(TSC_InitStruct->TSC_BiasAdj));

    /* Set CR */
    TSC->CR = TSC_InitStruct->TSC_Discard | TSC_InitStruct->TSC_Mode | \
              (TSC_InitStruct->TSC_DigitalPrediv << 12) | (TSC_InitStruct->TSC_AnalogPrediv << 24) | \
              (TSC_InitStruct->TSC_BiasAdj << 20) | TSC_CR_ANA_ENABLE;
}

/**
  * @brief  Enables or disables TSC .
  * @param  PIO: specifies the pins. 
  *          This parameter can be any combination of the following values:
  *            @arg TSC_ENABLE_PIO0_0
  *            @arg TSC_ENABLE_PIO0_1
  *            @arg TSC_ENABLE_PIO0_2
  *            @arg TSC_ENABLE_PIO0_3
  *            @arg TSC_ENABLE_PIO0_4
  *            @arg TSC_ENABLE_PIO0_5
  *            @arg TSC_ENABLE_PIO0_6
  *            @arg TSC_ENABLE_PIO0_7
  *            @arg TSC_ENABLE_PIO1_0
  *            @arg TSC_ENABLE_PIO1_1
  *            @arg TSC_ENABLE_PIO1_2
  *            @arg TSC_ENABLE_PIO1_3
  *            @arg TSC_ENABLE_PIO1_4
  *            @arg TSC_ENABLE_PIO1_5
  *            @arg TSC_ENABLE_PIO1_6
  *            @arg TSC_ENABLE_PIO1_7
  *            @arg TSC_ENABLE_PIO2_0
  *            @arg TSC_ENABLE_PIO2_1
  *            @arg TSC_ENABLE_PIO2_2
  *            @arg TSC_ENABLE_PIO2_3
  * @param  NewState: new state of the TSC. 
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void TSC_Cmd(uint32_t PIO, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_TSC_ENABLE_PIO(PIO));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable TSC */
        TSC->ENABLE = PIO;
    }
    else
    {
        /* Disable TSC */
        TSC->ENABLE &= ~PIO;
    }
}

/**
  * @brief  Set TSC mode.
  * @param  Mode: specifies tsc mode. 
  *          This parameter can be one of the following values:
  *            @arg TSC_CR_SCAN
  *            @arg TSC_CR_POLL
  * @retval None
  */
void TSC_SetMode(uint32_t Mode)
{
    uint32_t temp_reg;
    
    /* Check the parameters */
    assert_param(IS_TSC_MODE(Mode));

    temp_reg = TSC->CR;
    temp_reg &= ~(TSC_CR_SCAN | TSC_CR_POLL);
    temp_reg |= Mode;
    TSC->CR = temp_reg;
}

/**
  * @brief  Returns TSC sample result data.  
  * @param  TSC_IO: TSC IO
  *         This parameter can be one of the following values:
  *            @arg TSC_IO_PIOx_y(x[0:2], y[0-7])
  *                 (TSC_IO_PIO0_0 -- TSC_IO_PIO2_2)
  * @retval The sample value.
  */
uint16_t TSC_GetSampleValue(uint32_t TSC_IO)
{
    uint16_t temp;
    
    /* Check the parameters */
    assert_param(IS_TSC_GET_SAMPLE_VALUE_IO(TSC_IO));

    /* Return the selected TSC sample value */
    switch(TSC_IO)
    {
        case TSC_IO_PIO0_0:
            temp = (TSC->IOCCR0 >> 0) & 0x7FFF;
        break;
        
        case TSC_IO_PIO0_1:
            temp = (TSC->IOCCR0 >> 16) & 0x7FFF;
        break;
        
        case TSC_IO_PIO0_2:
            temp = (TSC->IOCCR1 >> 0) & 0x7FFF;
        break;
        
        case TSC_IO_PIO0_3:
            temp = (TSC->IOCCR1 >> 16) & 0x7FFF;
        break;
        
        case TSC_IO_PIO0_4:
            temp = (TSC->IOCCR2 >> 0) & 0x7FFF;
        break;
        
        case TSC_IO_PIO0_5:
            temp = (TSC->IOCCR2 >> 16) & 0x7FFF;
        break;
        
        case TSC_IO_PIO0_6:
            temp = (TSC->IOCCR3 >> 0) & 0x7FFF;
        break;
        
        case TSC_IO_PIO0_7:
            temp = (TSC->IOCCR3 >> 16) & 0x7FFF;
        break;
        
        case TSC_IO_PIO1_0:
            temp = (TSC->IOCCR4 >> 0) & 0x7FFF;
        break;
        
        case TSC_IO_PIO1_1:
            temp = (TSC->IOCCR4 >> 16) & 0x7FFF;
        break;
        
        case TSC_IO_PIO1_2:
            temp = (TSC->IOCCR5 >> 0) & 0x7FFF;
        break;
        
        case TSC_IO_PIO1_3:
            temp = (TSC->IOCCR5 >> 16) & 0x7FFF;
        break;
        
        case TSC_IO_PIO1_4:
            temp = (TSC->IOCCR6 >> 0) & 0x7FFF;
        break;
        
        case TSC_IO_PIO1_5:
            temp = (TSC->IOCCR6 >> 16) & 0x7FFF;
        break;
        
        case TSC_IO_PIO1_6:
            temp = (TSC->IOCCR7 >> 0) & 0x7FFF;
        break;
        
        case TSC_IO_PIO1_7:
            temp = (TSC->IOCCR7 >> 16) & 0x7FFF;
        break;
        
        case TSC_IO_PIO2_0:
            temp = (TSC->IOCCR8 >> 0) & 0x7FFF;
        break;
        
        case TSC_IO_PIO2_1:
            temp = (TSC->IOCCR8 >> 16) & 0x7FFF;
        break;
        
        case TSC_IO_PIO2_2:
            temp = (TSC->IOCCR9 >> 0) & 0x7FFF;
        break;

        case TSC_IO_PIO2_3:
            temp = (TSC->IOCCR9 >> 16) & 0x7FFF;
        break;

        default:
            
        break;
    }

    return temp;
}

/**
  * @brief  Set TSC threshold value.
  * @param  TSC_IO: TSC IO
  *         This parameter can be one of the following values:
  *            @arg TSC_IO_PIOx_y(x[0:2], y[0-7])
  *                 (TSC_IO_PIO0_0 -- TSC_IO_PIO2_2)
  * @param  Value: 
  *         This parameter can be[1:32767].
  * @retval None.
  */
void TSC_SetThresholdValue(uint32_t TSC_IO, uint32_t Value)
{
    uint32_t temp;
    
    /* Check the parameters */
    assert_param(IS_TSC_SET_THRESHOLD_VALUE_IO(TSC_IO));
    assert_param(IS_TSC_SET_THRESHOLD_VALUE(Value));

    /* Return the selected TSC sample value */
    switch(TSC_IO)
    {
        case TSC_IO_PIO0_0:
            temp = TSC->IOCCR0;
            temp &= ~TSC_IOCCR0_VAL_PIO0_0_MASK;
            temp |= Value << 0;
            TSC->IOCCR0 = temp;
        break;
        
        case TSC_IO_PIO0_1:
            temp = TSC->IOCCR0;
            temp &= ~TSC_IOCCR0_VAL_PIO0_1_MASK;
            temp |= Value << 16;
            TSC->IOCCR0 = temp;
        break;
        
        case TSC_IO_PIO0_2:
            temp = TSC->IOCCR1;
            temp &= ~TSC_IOCCR1_VAL_PIO0_2_MASK;
            temp |= Value << 0;
            TSC->IOCCR1 = temp;
        break;
        
        case TSC_IO_PIO0_3:
            temp = TSC->IOCCR1;
            temp &= ~TSC_IOCCR1_VAL_PIO0_3_MASK;
            temp |= Value << 16;
            TSC->IOCCR1 = temp;
        break;
        
        case TSC_IO_PIO0_4:
            temp = TSC->IOCCR2;
            temp &= ~TSC_IOCCR2_VAL_PIO0_4_MASK;
            temp |= Value << 0;
            TSC->IOCCR2 = temp;
        break;
        
        case TSC_IO_PIO0_5:
            temp = TSC->IOCCR2;
            temp &= ~TSC_IOCCR2_VAL_PIO0_5_MASK;
            temp |= Value << 16;
            TSC->IOCCR2 = temp;
        break;
        
        case TSC_IO_PIO0_6:
            temp = TSC->IOCCR3;
            temp &= ~TSC_IOCCR3_VAL_PIO0_6_MASK;
            temp |= Value << 0;
            TSC->IOCCR3 = temp;
        break;
        
        case TSC_IO_PIO0_7:
            temp = TSC->IOCCR3;
            temp &= ~TSC_IOCCR3_VAL_PIO0_7_MASK;
            temp |= Value << 16;
            TSC->IOCCR3 = temp;
        break;
        
        case TSC_IO_PIO1_0:
            temp = TSC->IOCCR4;
            temp &= ~TSC_IOCCR4_VAL_PIO1_0_MASK;
            temp |= Value << 0;
            TSC->IOCCR4 = temp;
        break;
        
        case TSC_IO_PIO1_1:
            temp = TSC->IOCCR4;
            temp &= ~TSC_IOCCR4_VAL_PIO1_1_MASK;
            temp |= Value << 16;
            TSC->IOCCR4 = temp;
        break;
        
        case TSC_IO_PIO1_2:
            temp = TSC->IOCCR5;
            temp &= ~TSC_IOCCR5_VAL_PIO1_2_MASK;
            temp |= Value << 0;
            TSC->IOCCR5 = temp;
        break;
        
        case TSC_IO_PIO1_3:
            temp = TSC->IOCCR5;
            temp &= ~TSC_IOCCR5_VAL_PIO1_3_MASK;
            temp |= Value << 16;
            TSC->IOCCR5 = temp;
        break;
        
        case TSC_IO_PIO1_4:
            temp = TSC->IOCCR6;
            temp &= ~TSC_IOCCR6_VAL_PIO1_4_MASK;
            temp |= Value << 0;
            TSC->IOCCR6 = temp;
        break;
        
        case TSC_IO_PIO1_5:
            temp = TSC->IOCCR6;
            temp &= ~TSC_IOCCR6_VAL_PIO1_5_MASK;
            temp |= Value << 16;
            TSC->IOCCR6 = temp;
        break;
        
        case TSC_IO_PIO1_6:
            temp = TSC->IOCCR7;
            temp &= ~TSC_IOCCR7_VAL_PIO1_6_MASK;
            temp |= Value << 0;
            TSC->IOCCR7 = temp;
        break;
        
        case TSC_IO_PIO1_7:
            temp = TSC->IOCCR7;
            temp &= ~TSC_IOCCR7_VAL_PIO1_7_MASK;
            temp |= Value << 16;
            TSC->IOCCR7 = temp;
        break;
        
        case TSC_IO_PIO2_0:
            temp = TSC->IOCCR8;
            temp &= ~TSC_IOCCR8_VAL_PIO2_0_MASK;
            temp |= Value << 0;
            TSC->IOCCR8 = temp;
        break;
        
        case TSC_IO_PIO2_1:
            temp = TSC->IOCCR8;
            temp &= ~TSC_IOCCR8_VAL_PIO2_1_MASK;
            temp |= Value << 16;
            TSC->IOCCR8 = temp;
        break;
        
        case TSC_IO_PIO2_2:
            temp = TSC->IOCCR9;
            temp &= ~TSC_IOCCR9_VAL_PIO2_2_MASK;
            temp |= Value << 0;
            TSC->IOCCR9 = temp;
        break;

        case TSC_IO_PIO2_3:
            temp = TSC->IOCCR9;
            temp &= ~TSC_IOCCR9_VAL_PIO2_2_MASK;
            temp |= Value << 16;
            TSC->IOCCR9 = temp;
        break;

        default:
            
        break;
    }
}

/**
  * @brief  Checks whether the specified TSC flag is set or not.
  * @param  TSC_IO: TSC IO
  *         This parameter can be one of the following values:
  *            @arg TSC_IO_PIOx_y(x[0:2], y[0-7])
  *                 (TSC_IO_PIO0_0 -- TSC_IO_PIO2_2)
  * @retval The new state of TSC_FLAG (SET or RESET).
  */
FlagStatus TSC_GetFlagStatus(uint32_t TSC_IO)
{
    FlagStatus bitstatus = RESET;

    /* Check the parameters */
    assert_param(IS_TSC_GET_FLAG_IO(TSC_IO));

    /* Check the status of the specified TSC flag */
    if ((TSC->STAT & TSC_IO) != (uint32_t)RESET)
    {
        /* TSC_FLAG is set */
        bitstatus = SET;
    }
    else
    {
        /* TSC_FLAG is reset */
        bitstatus = RESET;
    }
    
    /* Return the TSC_FLAG status */
    return  bitstatus;
}

/**
  * @brief  Enables or disables the TSC interrupt.
  * @param  NewState: new state of the TSC interrupts.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void TSC_ITConfig(FunctionalState NewState)  
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the selected TSC interrupts */
        TSC->IER |=  (TSC_IER_ENABLE);
    }
    else
    {
        /* Disable the selected TSC interrupts */
        TSC->IER &= ~(TSC_IER_ENABLE);
    }
}

/**
  * @brief  Checks whether the TSC interrupt has occurred or not.
  * @retval The new state of TSC_IT (SET or RESET).
  */
ITStatus TSC_GetITStatus(void)
{
    ITStatus bitstatus = RESET;
    uint32_t enablestatus = 0;

    /* Get the TSC enable bit status */
    enablestatus = TSC->IER & TSC_IER_ENABLE;
  
    /* Check the status of the specified TSC interrupt */
    if (((TSC->ISR & TSC_ISR_STATUS) != (uint32_t)RESET) && enablestatus)
    {
        /* TSC_IT is set */
        bitstatus = SET;
    }
    else
    {
        /* TSC_IT is reset */
        bitstatus = RESET;
    }
    
    /* Return the TSC_IT status */
    return  bitstatus;
}

/**
  * @brief  Clears the TSC interrupt pending bits.
  * @retval None
  */
void TSC_ClearITPendingBit(void)
{
    /* Clear the selected TSC interrupt pending bits */
    TSC->ICR |= TSC_ICR_CLEAR;
}

/**
  * @}
  */ 

/**
  * @}
  */ 

/**
  * @}
  */ 

/******************* (C) COPYRIGHT WeiLink Technology *****END OF FILE****/
